package com.jinandi.app.domain;

import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.TableGenerator;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.jpa.domain.Specification;

@MappedSuperclass
public abstract class ManagedIdentityDomainObject<T extends ManagedIdentityDomainObject<T>>
		implements Serializable {

	private static final long serialVersionUID = -5051840048750767390L;
	protected Long id;

	@Id
	@TableGenerator(name = "JINANDI_ID", table = "JINANDI_ID_DB", pkColumnName = "pk_key", valueColumnName = "pk_value", allocationSize = 1, initialValue = 1)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "JINANDI_ID")
	@Column(nullable = false, insertable = false, updatable = false)
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	private transient int hashCode = Integer.MIN_VALUE;

	@Override
	public int hashCode() {
		if (Integer.MIN_VALUE == this.hashCode) {
			String hashStr = this.getClass().getName() + ":"
					+ this.id.hashCode();
			this.hashCode = hashStr.hashCode();
		}
		return this.hashCode;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public boolean equals(Object obj) {
		if (null == obj)
			return false;
		if (!(obj instanceof ManagedIdentityDomainObject))
			return false;
		else {
			ManagedIdentityDomainObject domainObject = (ManagedIdentityDomainObject) obj;
			if (null == this.id)
				return false;
			return this.id == domainObject.id;
		}
	}

	/**
	 * <动态拼装sql>
	 * 
	 * @param map
	 * @return
	 * @author CGC 创建日期:2013-4-19 下午1:06:44
	 */
	public final Specification<T> getSpecification(final Map<String, Object> map) {
		return new Specification<T>() {
			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> cq,
					CriteriaBuilder builder) {
				Predicate predicate = builder.equal(builder.literal(1), 1);
				if (!map.isEmpty()) {
					for (Entry<String, Object> entry : map.entrySet()) {
						predicate = builder.and(
								predicate,
								builder.equal(root.get(entry.getKey()),
										entry.getValue()));
					}
				}
				return predicate;
			}
		};
	}
}
